package com.k8sops.backend.service.impl;

import com.k8sops.backend.common.BusinessException;
import com.k8sops.backend.entity.Menu;
import com.k8sops.backend.mapper.MenuMapper;
import com.k8sops.backend.mapper.RoleMenuRelationMapper;
import com.k8sops.backend.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * u83dcu5355u670du52a1u5b9eu73b0u7c7b
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuRelationMapper roleMenuRelationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Menu createMenu(Menu menu) {
        // u68c0u67e5u7236u83dcu5355u662fu5426u5b58u5728
        if (menu.getParentMenuId() != null && menu.getParentMenuId() > 0) {
            Menu parentMenu = menuMapper.selectById(menu.getParentMenuId());
            if (parentMenu == null) {
                throw new BusinessException("u7236u83dcu5355u4e0du5b58u5728");
            }
        }
        
        // u63d2u5165u83dcu5355u8bb0u5f55
        menuMapper.insert(menu);
        return menu;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Menu updateMenu(Menu menu) {
        // u68c0u67e5u83dcu5355u662fu5426u5b58u5728
        Menu existingMenu = menuMapper.selectById(menu.getId());
        if (existingMenu == null) {
            throw new BusinessException("u83dcu5355u4e0du5b58u5728");
        }
        
        // u68c0u67e5u7236u83dcu5355u662fu5426u5b58u5728
        if (menu.getParentMenuId() != null && menu.getParentMenuId() > 0) {
            Menu parentMenu = menuMapper.selectById(menu.getParentMenuId());
            if (parentMenu == null) {
                throw new BusinessException("u7236u83dcu5355u4e0du5b58u5728");
            }
            
            // u68c0u67e5u662fu5426u5c06u81eau5df1u8bbeu7f6eu4e3au81eau5df1u7684u7236u83dcu5355
            if (menu.getId().equals(menu.getParentMenuId())) {
                throw new BusinessException("u4e0du80fdu5c06u83dcu5355u7684u7236u83dcu5355u8bbeu7f6eu4e3au81eau5df1");
            }
        }
        
        // u66f4u65b0u83dcu5355u8bb0u5f55
        menuMapper.update(menu);
        return menuMapper.selectById(menu.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteMenu(Long menuId) {
        // u68c0u67e5u83dcu5355u662fu5426u5b58u5728
        Menu existingMenu = menuMapper.selectById(menuId);
        if (existingMenu == null) {
            throw new BusinessException("u83dcu5355u4e0du5b58u5728");
        }
        
        // u68c0u67e5u662fu5426u6709u5b50u83dcu5355
        List<Menu> children = menuMapper.selectByParentId(menuId);
        if (children != null && !children.isEmpty()) {
            throw new BusinessException("u8be5u83dcu5355u4e0bu6709u5b50u83dcu5355uff0cu4e0du80fdu76f4u63a5u5220u9664");
        }
        
        // u5220u9664u83dcu5355u76f8u5173u7684u89d2u8272u83dcu5355u5173u8054
        roleMenuRelationMapper.deleteByMenuId(menuId);
        
        // u5220u9664u83dcu5355u8bb0u5f55
        return menuMapper.deleteById(menuId) > 0;
    }

    @Override
    public Menu getMenuById(Long menuId) {
        return menuMapper.selectById(menuId);
    }

    @Override
    public List<Menu> getAllMenus() {
        return menuMapper.selectAll();
    }

    @Override
    public List<Menu> getMenuTree() {
        // u83b7u53d6u6240u6709u83dcu5355
        List<Menu> allMenus = menuMapper.selectAll();
        return buildMenuTree(allMenus, null);
    }

    @Override
    public List<Menu> getMenusByRoleId(Long roleId) {
        return menuMapper.selectMenusByRoleId(roleId);
    }

    @Override
    public List<Menu> getMenuTreeByRoleId(Long roleId) {
        // u83b7u53d6u89d2u8272u7684u6240u6709u83dcu5355
        List<Menu> roleMenus = menuMapper.selectMenusByRoleId(roleId);
        return buildMenuTree(roleMenus, null);
    }
    
    /**
     * u6784u5efau83dcu5355u6811
     * @param menus u83dcu5355u5217u8868
     * @param parentId u7236u83dcu5355ID
     * @return u83dcu5355u6811
     */
    private List<Menu> buildMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> result = new ArrayList<>();
        
        // u5c06u83dcu5355u6309u7167u7236u83dcu5355IDu5206u7ec4
        Map<Long, List<Menu>> menuMap = new HashMap<>();
        for (Menu menu : menus) {
            Long pid = menu.getParentMenuId() == null ? 0L : menu.getParentMenuId();
            if (!menuMap.containsKey(pid)) {
                menuMap.put(pid, new ArrayList<>());
            }
            menuMap.get(pid).add(menu);
        }
        
        // u83b7u53d6u7236u83dcu5355IDu5bf9u5e94u7684u5b50u83dcu5355u5217u8868
        Long pid = parentId == null ? 0L : parentId;
        List<Menu> children = menuMap.get(pid);
        
        if (children != null) {
            // u6309u7167u6392u5e8fu53f7u6392u5e8f
            children = children.stream()
                    .sorted((m1, m2) -> {
                        int order1 = m1.getOrderNum() == null ? 0 : m1.getOrderNum();
                        int order2 = m2.getOrderNum() == null ? 0 : m2.getOrderNum();
                        return order1 - order2;
                    })
                    .collect(Collectors.toList());
            
            // u9012u5f52u6784u5efau5b50u83dcu5355u7684u6811u7ed3u6784
            for (Menu child : children) {
                result.add(child);
            }
        }
        
        return result;
    }
}
